/*
 * @(#)DrawProject.java  1.2  2006-12-26
 *
 * Copyright (c) 1996-2006 by the original authors of JHotDraw
 * and all its contributors ("JHotDraw.org")
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JHotDraw.org ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance
 * with the terms of the license agreement you entered into with
 * JHotDraw.org.
 *
 */
package com.thoughtworks.studio.tools.cardkit.gui;

import java.awt.BorderLayout;
import java.awt.Insets;
import java.awt.print.Pageable;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.prefs.Preferences;

import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;

import org.apache.log4j.Logger;
import org.jhotdraw.app.AbstractProject;
import org.jhotdraw.app.action.RedoAction;
import org.jhotdraw.app.action.UndoAction;
import org.jhotdraw.draw.Constrainer;
import org.jhotdraw.draw.DOMStorableInputOutputFormat;
import org.jhotdraw.draw.DefaultDrawing;
import org.jhotdraw.draw.DefaultDrawingEditor;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.DrawingEditor;
import org.jhotdraw.draw.DrawingPageable;
import org.jhotdraw.draw.Figure;
import org.jhotdraw.draw.GridConstrainer;
import org.jhotdraw.draw.ImageOutputFormat;
import org.jhotdraw.draw.InputFormat;
import org.jhotdraw.draw.OutputFormat;
import org.jhotdraw.draw.action.ButtonFactory;
import org.jhotdraw.gui.PlacardScrollPaneLayout;
import org.jhotdraw.io.ExtensionFileFilter;
import org.jhotdraw.undo.UndoRedoManager;
import org.jhotdraw.util.ResourceBundleUtil;

import com.thoughtworks.studio.tools.cardkit.Card;
import com.thoughtworks.studio.tools.cardkit.gui.figures.CardFigure;

/**
 * A story wall drawing project.
 */
public class CardkitProject extends AbstractProject {

	private Logger logger = Logger.getLogger(CardkitProject.class);
	private FindDialog findDialog;
	/**
	 * Each DrawProject uses its own undo redo manager. This allows for undoing
	 * and redoing actions per project.
	 */
	private UndoRedoManager undo;

	/**
	 * Depending on the type of an application, there may be one editor per
	 * project, or a single shared editor for all projects.
	 */
	private DrawingEditor editor;

	private GridConstrainer visibleConstrainer = new GridConstrainer(10, 10);
	private GridConstrainer invisibleConstrainer = new GridConstrainer(1, 1);
	private Preferences prefs;

	/**
	 * Creates a new Project.
	 */
	public CardkitProject() {
	}

	/**
	 * Initializes the project.
	 */
	public void init() {
		super.init();

		initComponents();

		JPanel zoomButtonPanel = new JPanel(new BorderLayout());
		scrollPane.setLayout(new PlacardScrollPaneLayout());
		scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0));

		setEditor(new DefaultDrawingEditor());
		undo = new UndoRedoManager();
		view.setDrawing(createDrawing());
		view.getDrawing().addUndoableEditListener(undo);
		
		initActions();
		undo.addPropertyChangeListener(new PropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent evt) {
				setHasUnsavedChanges(undo.hasSignificantEdits());
			}
		});

		ResourceBundleUtil labels = ResourceBundleUtil
				.getLAFBundle("org.jhotdraw.draw.Labels");

		JPanel placardPanel = new JPanel(new BorderLayout());
		javax.swing.AbstractButton pButton;
		pButton = ButtonFactory.createZoomButton(view);
		pButton.putClientProperty("Quaqua.Button.style", "placard");
		pButton.putClientProperty("Quaqua.Component.visualMargin", new Insets(
				0, 0, 0, 0));
		pButton.setFont(UIManager.getFont("SmallSystemFont"));
		placardPanel.add(pButton, BorderLayout.WEST);
		pButton = ButtonFactory.createToggleGridButton(view);
		pButton.putClientProperty("Quaqua.Button.style", "placard");
		pButton.putClientProperty("Quaqua.Component.visualMargin", new Insets(
				0, 0, 0, 0));
		pButton.setFont(UIManager.getFont("SmallSystemFont"));
		labels.configureToolBarButton(pButton, "alignGridSmall");
		placardPanel.add(pButton, BorderLayout.EAST);
		scrollPane.add(placardPanel, JScrollPane.LOWER_LEFT_CORNER);

		prefs = Preferences.userNodeForPackage(getClass());
		setGridVisible(prefs.getBoolean("project.gridVisible", false));
		setScaleFactor(prefs.getDouble("project.scaleFactor", 1d));
	}

	/**
	 * Creates a new Drawing for this Project.
	 */
	protected Drawing createDrawing() {
		DefaultDrawing drawing = new DefaultDrawing();
		DOMStorableInputOutputFormat ioFormat = new DOMStorableInputOutputFormat(
				new CardkitFactory());
		LinkedList<InputFormat> inputFormats = new LinkedList<InputFormat>();
		inputFormats.add(ioFormat);
		drawing.setInputFormats(inputFormats);
		LinkedList<OutputFormat> outputFormats = new LinkedList<OutputFormat>();
		outputFormats.add(ioFormat);
		outputFormats.add(new ImageOutputFormat());
		drawing.setOutputFormats(outputFormats);
		return drawing;
	}

	/**
	 * Creates a Pageable object for printing the project.
	 */
	public Pageable createPageable() {
		return new DrawingPageable(view.getDrawing());

	}

	public DrawingEditor getEditor() {
		return editor;
	}

	public void setEditor(DrawingEditor newValue) {
		DrawingEditor oldValue = editor;
		if (oldValue != null) {
			oldValue.remove(view);
		}
		editor = newValue;
		if (newValue != null) {
			newValue.add(view);
		}
	}

	public void setGridVisible(boolean newValue) {
		boolean oldValue = isGridVisible();
		Constrainer c = (newValue) ? visibleConstrainer : invisibleConstrainer;
		view.setConstrainer(c);

		firePropertyChange("gridVisible", oldValue, newValue);
		prefs.putBoolean("project.gridVisible", newValue);
	}

	public boolean isGridVisible() {
		return view.getConstrainer() == visibleConstrainer;
	}

	public double getScaleFactor() {
		return view.getScaleFactor();
	}

	public void setScaleFactor(double newValue) {
		double oldValue = getScaleFactor();
		view.setScaleFactor(newValue);

		firePropertyChange("scaleFactor", oldValue, newValue);
		prefs.putDouble("project.scaleFactor", newValue);
	}

	/**
	 * Initializes project specific actions.
	 */
	private void initActions() {
		putAction(UndoAction.ID, undo.getUndoAction());
		putAction(RedoAction.ID, undo.getRedoAction());
	}

	protected void setHasUnsavedChanges(boolean newValue) {
		super.setHasUnsavedChanges(newValue);
		undo.setHasSignificantEdits(newValue);
	}

	/**
	 * Writes the project to the specified file.
	 */
	public void write(File f) {
		Drawing drawing = view.getDrawing();
		List<OutputFormat> formats = drawing.getOutputFormats();
		if (formats.isEmpty()) {
			LinkedList<OutputFormat> outputFormats = new LinkedList<OutputFormat>();
			List<InputFormat> inputs = drawing.getInputFormats();
			if (inputs.isEmpty() || (inputs.size() != 2)) {
				DOMStorableInputOutputFormat ioFormat = new DOMStorableInputOutputFormat(
						new CardkitFactory());
				formats.add(ioFormat);
			} else {
				outputFormats.add((DOMStorableInputOutputFormat) inputs.get(0));
			}
		}
		formats.add(new ImageOutputFormat());
		drawing.setOutputFormats(formats);
		OutputFormat outputFormat = drawing.getOutputFormats().get(0);
		try {
			outputFormat.write(f, drawing);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Reads the project from the specified file.
	 */
	public void read(File f) throws IOException {
		try {
			final Drawing drawing = createDrawing();
			InputFormat inputFormat = drawing.getInputFormats().get(0);
			inputFormat.read(f, drawing);
			SwingUtilities.invokeAndWait(new Runnable() {
				public void run() {
					view.getDrawing().removeUndoableEditListener(undo);
					view.setDrawing(drawing);
					view.getDrawing().addUndoableEditListener(undo);
					undo.discardAllEdits();
				}
			});
		} catch (InterruptedException e) {
			InternalError error = new InternalError();
			e.initCause(e);
			throw error;
		} catch (InvocationTargetException e) {
			InternalError error = new InternalError();
			e.initCause(e);
			throw error;
		}
	}

	/**
	 * Sets a drawing editor for the project.
	 */
	public void setDrawingEditor(DrawingEditor newValue) {
		if (editor != null) {
			editor.remove(view);
		}
		editor = newValue;
		if (editor != null) {
			editor.add(view);
		}
	}

	/**
	 * Gets the drawing editor of the project.
	 */
	public DrawingEditor getDrawingEditor() {
		return editor;
	}

	/**
	 * Clears the project.
	 */
	public void clear() {
		view.setDrawing(new DefaultDrawing());
		undo.discardAllEdits();
	}

	@Override
	protected JFileChooser createOpenChooser() {
		JFileChooser c = super.createOpenChooser();
		c
				.addChoosableFileFilter(new ExtensionFileFilter("Story Diagram",
						"xml"));
		return c;
	}

	@Override
	protected JFileChooser createSaveChooser() {
		JFileChooser c = super.createSaveChooser();
		c
				.addChoosableFileFilter(new ExtensionFileFilter("Story Diagram",
						"xml"));
		return c;
	}

	public void findCardByNumber(){
		if (findDialog == null) {
			findDialog = new FindDialog(this.getApplication());
		}
		findDialog.setVisible(true);
		List<Figure> figures = view.getDrawing().getFigures();
		Figure figure = null;
		for (Iterator iterator = figures.iterator(); iterator.hasNext();) {
			figure= (Figure) iterator.next();
			if(figure instanceof CardFigure){
				Card card=((CardFigure)figure).getCard();
				if(card.getNumber().toString().equals(findDialog.getCardnumber())){
					System.out.println("get it");
				}
			}
		}
		view.getDrawing().bringToFront(figure);		
	}
	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	// <editor-fold defaultstate="collapsed" desc=" Generated Code
	// ">//GEN-BEGIN:initComponents
	private void initComponents() {
		scrollPane = new javax.swing.JScrollPane();
		view = new org.jhotdraw.draw.DefaultDrawingView();

		setLayout(new java.awt.BorderLayout());

		scrollPane
				.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
		scrollPane
				.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrollPane.setViewportView(view);

		add(scrollPane, java.awt.BorderLayout.CENTER);

	}// </editor-fold>//GEN-END:initComponents

	// Variables declaration - do not modify//GEN-BEGIN:variables
	private javax.swing.JScrollPane scrollPane;
	private org.jhotdraw.draw.DefaultDrawingView view;
	// End of variables declaration//GEN-END:variables

}
